/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.flipkart.ohos.proteus;

import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

import java.util.Locale;

/**
 * 日志打印工具类, 可以设置屏蔽等级 {@link #setLogLevel(int)}, 设置 {@link #LOG_LEVEL_OFF} 将屏蔽所有日志
 *
 * @since 2021-04-18
 */
public final class LogUtil {
    private static final String DEF_LOG_TAG = "Photos";
    private static final int DEF_LOG_DOMAIN = 0x00201;
    private static final HiLogLabel DEF_LOG_LABEL = new HiLogLabel(HiLog.LOG_APP, DEF_LOG_DOMAIN, DEF_LOG_TAG);
    private static Log logImpl = new DefaultLogImpl();

    /**
     * 应用调试级别，默认不输出，仅在开启"USB调试"模式下可用
     */
    private static final int LOG_LEVEL_DEBUG = 5;

    /**
     * 普通级别信息
     */
    private static final int LOG_LEVEL_INFO = 4;

    /**
     * 警告级别信息
     */
    private static final int LOG_LEVEL_WARN = 3;

    /**
     * 错误级别信息
     */
    private static final int LOG_LEVEL_ERROR = 2;

    /**
     * 致命错误、不可恢复错误级别信息
     */
    private static final int LOG_LEVEL_FATAL = 1;

    /**
     * 屏蔽所有日志
     */
    private static final int LOG_LEVEL_OFF = 0;

    /**
     * 当前设置日志过滤级别
     */
    private static int curLogLevel = LOG_LEVEL_DEBUG;

    private LogUtil() {
    }

    /**
     * 设置日志输出过滤级别,设置 {@link LogUtil#LOG_LEVEL_OFF}为关闭所有日志
     *
     * @param logLevel 日志拦截级别
     */
    public static void setLogLevel(int logLevel) {
        curLogLevel = logLevel;
    }

    /**
     * 设置Log打印Impl
     *
     * @param logImpl Log打印实现替换 {@link LogUtil.Log}
     */
    public static void setLogImpl(Log logImpl) {
        LogUtil.logImpl = logImpl;
    }

    private static boolean enableLog(int target) {
        return curLogLevel >= target;
    }

    private static boolean isEmpty(Object[] array) {
        return array == null || array.length == 0;
    }

    /**
     * 打印debug级别日志
     *
     * @param label 日志标签
     * @param format log或format
     * @param value format参数,可为空
     */
    public static void debug(HiLogLabel label, String format, Object... value) {
        if (enableLog(LOG_LEVEL_DEBUG)) {
            String msg = isEmpty(value) ? format : String.format(Locale.ROOT, format, value);
            logImpl.debug(label, msg);
        }
    }

    /**
     * 打印DEBUG级别日志
     *
     * @param tag 日志标签
     * @param message 信息
     */
    public static void debug(String tag, String message) {
        logImpl.debug(tag, message);
    }

    /**
     * 打印INFO级别日志
     *
     * @param label 日志标签
     * @param format log或format
     * @param value format参数,可为空
     */
    public static void info(HiLogLabel label, String format, Object... value) {
        if (enableLog(LOG_LEVEL_INFO)) {
            String msg = isEmpty(value) ? format : String.format(Locale.ROOT, format, value);
            logImpl.info(label, msg);
        }
    }

    /**
     * 打印INFO级别日志
     *
     * @param tag 日志标签
     * @param message 信息
     */
    public static void info(String tag, String message) {
        logImpl.info(tag, message);
    }

    /**
     * 打印WARN级别日志
     *
     * @param label 日志标签
     * @param format log或format
     * @param value format参数,可为空
     */
    public static void warn(HiLogLabel label, String format, Object... value) {
        if (enableLog(LOG_LEVEL_WARN)) {
            String msg = isEmpty(value) ? format : String.format(Locale.ROOT, format, value);
            logImpl.warn(label, msg);
        }
    }

    /**
     * 打印WARN级别日志
     *
     * @param tag 日志标签
     * @param message 信息
     */
    public static void warn(String tag, String message) {
        logImpl.warn(tag, message);
    }

    /**
     * 打印ERROR级别日志
     *
     * @param label 日志标签
     * @param format log或format
     * @param value format参数,可为空
     */
    public static void error(HiLogLabel label, String format, Object... value) {
        if (enableLog(LOG_LEVEL_ERROR)) {
            String msg = isEmpty(value) ? format : String.format(Locale.ROOT, format, value);
            logImpl.error(label, msg);
        }
    }

    /**
     * 打印ERROR级别日志
     *
     * @param tag 日志标签
     * @param message 信息
     */
    public static void error(String tag, String message) {
        logImpl.error(tag, message);
    }

    /**
     * 输出异常关键信息
     *
     * @param tr 异常
     */
    public static void error(Throwable tr) {
        if (enableLog(LOG_LEVEL_ERROR)) {
            logImpl.error(tr);
        }
    }

    /**
     * 打印FATAL级别日志
     *
     * @param label 日志标签
     * @param format log或format
     * @param value format参数,可为空
     */
    public static void fatal(HiLogLabel label, String format, Object... value) {
        if (enableLog(LOG_LEVEL_FATAL)) {
            String msg = isEmpty(value) ? format : String.format(Locale.ROOT, format, value);
            logImpl.fatal(label, msg);
        }
    }

    /**
     * 默认HiLog打印实现
     *
     * @since 2021-02-18
     */
    public static class DefaultLogImpl implements Log {
        private static final String TAG_MSG_SPLIT = ":";

        @Override
        public void debug(HiLogLabel label, String message) {
            HiLog.debug(label, message);
        }

        @Override
        public void debug(String tag, String message) {
            warn(DEF_LOG_LABEL, tag + TAG_MSG_SPLIT + message);
        }

        @Override
        public void info(HiLogLabel label, String message) {
            HiLog.info(label, message);
        }

        @Override
        public void info(String tag, String message) {
            info(DEF_LOG_LABEL, tag + TAG_MSG_SPLIT + message);
        }

        @Override
        public void warn(HiLogLabel label, String message) {
            HiLog.warn(label, message);
        }

        @Override
        public void warn(String tag, String message) {
            warn(DEF_LOG_LABEL, tag + TAG_MSG_SPLIT + message);
        }

        @Override
        public void error(HiLogLabel label, String message) {
            HiLog.error(label, message);
        }

        @Override
        public void error(String tag, String message) {
            error(DEF_LOG_LABEL, tag + TAG_MSG_SPLIT + message);
        }

        @Override
        public void error(Throwable tr) {
            HiLog.error(LogUtil.DEF_LOG_LABEL, HiLog.getStackTrace(tr));
        }

        @Override
        public void fatal(HiLogLabel label, String message) {
            HiLog.fatal(label, message);
        }
    }

    /**
     * 日志打印实现类的抽象接口
     *
     * @since 2021-02-18
     */
    public interface Log {
        /**
         * 打印调试级别日志
         *
         * @param label 日志标签
         * @param message 日志信息
         */
        void debug(HiLogLabel label, String message);

        /**
         * 打印调试级别日志
         *
         * @param tag 日志标签
         * @param message 日志信息
         */
        void debug(String tag, String message);

        /**
         * 打印普通信息级别日志
         *
         * @param label 日志标签
         * @param message 日志信息
         */
        void info(HiLogLabel label, String message);

        /**
         * 打印普通级别日志
         *
         * @param tag 日志标签
         * @param message 日志信息
         */
        void info(String tag, String message);

        /**
         * 打印警告级别日志
         *
         * @param label 日志标签
         * @param message 日志信息
         */
        void warn(HiLogLabel label, String message);

        /**
         * 打印警告级别日志
         *
         * @param tag 日志标签
         * @param message 日志信息
         */
        void warn(String tag, String message);

        /**
         * 打印错误级别日志
         *
         * @param label 日志标签
         * @param message 日志信息
         */
        void error(HiLogLabel label, String message);

        /**
         * 打印错误级别日志
         *
         * @param tag 日志标签
         * @param message 日志信息
         */
        void error(String tag, String message);

        /**
         * 打印异常关键信息
         *
         * @param tr 异常
         */
        void error(Throwable tr);

        /**
         * 打印致命级别日志
         *
         * @param label 日志标签
         * @param message 日志信息
         */
        void fatal(HiLogLabel label, String message);
    }
}

